<!--
 * @Author: jiangyg email@jiangyg.com
 * @Date: 2022-11-12 05:49:58
 * @LastEditors: jiangyg email@jiangyg.com
 * @LastEditTime: 2022-11-24 07:35:32
 * @FilePath: /frontend/mall-frontend/src/views/modules/admin/main-content.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <el-main class="site-content">
    <el-tabs class="site-tabs" type="card" v-model="tabsActiveName" @tab-click="selectedTabHandle" @tab-remove="removeTabHandle">
      <el-tab-pane v-for="item in mainTabs" :key="item.name" :name="item.name" :closable="item.closable">
        <template #label>
          <el-dropdown trigger="contextmenu">
            <span class="el-dropdown-link">
              {{ item.title }}
            </span>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item v-if="item.closable" @click="tabsCloseCurrentHandle">关闭当前标签页</el-dropdown-item>
                <el-dropdown-item @click="tabsCloseOtherHandle">关闭其它标签页</el-dropdown-item>
                <el-dropdown-item @click="tabsCloseAllHandle">关闭全部标签页</el-dropdown-item>
                <el-dropdown-item @click="tabsRefreshCurrentHandle">刷新当前标签页</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </template>
        <div class="st-tab-pane" :style="contentStyle">
          <el-scrollbar>
            <div class="sttp-body">
              <iframe v-if="item.type === 'iframe'" :src="item.iframeUrl" width="100%" height="100%" frameborder="0" scrolling="yes" />
              <router-view v-if="item.name === tabsActiveName" v-slot="{ Component }">
                <keep-alive>
                  <component :is="Component" />
                </keep-alive>
              </router-view>
            </div>
          </el-scrollbar>
        </div>
      </el-tab-pane>
    </el-tabs>
  </el-main>
</template>

<script lang="ts" setup>
import admin from "@/utils/admin";
import store from "@/store/index";
import { useRoute, useRouter } from "vue-router";
import { isURL } from "@/utils/index";
import { ref, computed, watch, nextTick } from "vue";

const route = useRoute();
const router = useRouter();

// 已打开tab集合
const mainTabs = computed(() => store.getters["mainTabs"]);

// 内容区域样式
const contentStyle = computed(() => {
  let contentHeight = store.getters["documentClientHeight"] - 50 - 34 + "px";
  return { border: 0, height: contentHeight, "max-height": contentHeight, overflow: "hidden" };
});

// 当前选中的tab页名称
const tabsActiveName = ref("");

// 选中tab标签处理
const selectedTabHandle = (pane, ev: Event) => {
  let tabs = mainTabs.value.filter((item) => item.name === pane.props.name);
  if (tabs.length >= 1) {
    let tab = tabs[0];
    router.push({ name: tab.name, query: tab.query, params: tab.params });
  }
};

// 移除tab标签处理
const removeTabHandle = (name) => {
  let $mainTabs = store.getters["mainTabs"];
  let tabs = $mainTabs && $mainTabs.filter((item) => item.name !== name);
  store.commit("mainTabs", tabs);
  if (tabs.length >= 1) {
    // 当前选中tab被删除
    if (name === tabsActiveName.value) {
      var tab = tabs[tabs.length - 1];
      router.push({ name: tab.name, query: tab.query, params: tab.params });
    }
  } else {
    tabsActiveName.value = "";
    router.push({ name: "admin-home" });
  }
};

// 关闭当前标签页
const tabsCloseCurrentHandle = () => {
  removeTabHandle(tabsActiveName.value);
};

// 关闭其它标签页
const tabsCloseOtherHandle = () => {
  let $mainTabs = store.getters["mainTabs"];
  let tabs = $mainTabs && $mainTabs.filter((item) => item.name === tabsActiveName.value);
  store.commit("mainTabs", tabs);
};

// 关闭全部标签页
const tabsCloseAllHandle = () => {
  store.commit("mainTabs", []);
  tabsActiveName.value = "";
  router.push({ name: "admin-home" });
};

// 刷新当前标签页
const tabsRefreshCurrentHandle = () => {
  let $mainTabs = store.getters["mainTabs"];
  let tabs = $mainTabs && $mainTabs.filter((item) => item.name === tabsActiveName.value);
  removeTabHandle(tabsActiveName.value);
  nextTick(() => {
    router.push({ name: tabs[0].name, query: tabs[0].query, params: tabs[0].params });
  });
};

// 构建tab对象
const buildTabObject = (route) => {
  return {
    id: route.meta.id || route.name,
    name: route.name,
    title: route.meta.name,
    type: isURL(route.meta.iframeUrl) ? "iframe" : "module",
    closable: route.meta.closable,
    iframeUrl: route.meta.iframeUrl || "",
    params: route.params,
    query: route.query,
  };
};

// 查找指定名称的路由
const findRouterByName = (name, routes) => {
  for (let i = 0; i < routes.length; i++) {
    let item = routes[i];
    if (item.name === name) {
      return item;
    }
    if (item.children && item.children.length > 0) {
      let child = findRouterByName(name, item.children);
      if (child) {
        return child;
      }
    }
  }
  return undefined;
};

// 根据路由ID查询面包屑路径
const findBreadcrumbByName = (id, menuList, breadcrumb) => {
  for (let i = 0; i < menuList.length; i++) {
    let item = menuList[i];
    if (item.id === id) {
      breadcrumb.push(item);
      return item;
    }
    if (item.children && item.children.length > 0) {
      let child = findBreadcrumbByName(id, item.children, breadcrumb);
      if (child) {
        breadcrumb.push(item);
        return item;
      }
    }
  }
  return undefined;
};

// 监听路由变化
watch(
  () => route,
  (newRoute, oldRoute) => {
    // 如果只是跳转主页面则再次跳转首页（默认打开首页）
    if (newRoute.name === 'admin') {
      router.replace({ name: 'admin-home' });
      return;
    }
    // 如果新路由是tab页则进行如下操作
    if (newRoute.meta.tab) {
      // 面包屑路径处理
      if (newRoute.meta && newRoute.meta.id) {
        let breadcrumb = [];
        findBreadcrumbByName(newRoute.meta.id, admin.menuList(), breadcrumb);
        store.commit("breadcrumb", breadcrumb.reverse());
      }
      let ntabs = [];
      let $mainTabs = store.getters["mainTabs"];
      // 如果不存在tab时，一般为刷新页面造成的，手动追加首页
      if ($mainTabs.length === 0 && newRoute.name !== 'admin-home') {
        let homeRouter = findRouterByName('admin-home', router.options.routes);
        let homeTabObj = buildTabObject(homeRouter);
        tabsActiveName.value = homeTabObj.name;
        ntabs.push(homeTabObj);
      }
      // 追加路由
      let tabObj = $mainTabs && $mainTabs.filter((item) => item.name === newRoute.name)[0];
      if (!tabObj) {
        if (newRoute.meta.dynamic) {
          let dynamicRouteList = admin.dynamicRouteList();
          if (dynamicRouteList.filter((item) => item.name === newRoute.name).length <= 0) {
            console.error("未能找到可用标签页!");
            return;
          }
        }
        tabObj = buildTabObject(newRoute);
        ntabs.push(tabObj);
      }
      tabsActiveName.value = tabObj.name;
      // 如果tab有变化则记录并重新渲染
      if (ntabs.length > 0) {
        store.commit("mainTabs", $mainTabs.concat(ntabs));
      }
    }
  },
  {
    immediate: true,
    deep: true,
  }
);
</script>

<style lang="scss">
$main-tab-height: 26px;

.site-content {
  padding: 0;
  overflow: hidden;

  > .site-tabs {
    overflow: hidden;

    > .el-tabs__header {
      height: auto;
      border: 0;
      margin: 0;
      border-bottom: 1px solid var(--el-border-color-light);

      .el-tabs__nav {
        border: 0;
        margin-left: 10px;

        .el-tabs__item {
          margin: 4px;
          padding: 0 10px !important;
          height: $main-tab-height;
          line-height: $main-tab-height;
          border: 1px solid #d8dce5;
          background: #fff;

          .el-icon {
            width: 14px !important;
          }

          span {
            color: #495060;
            line-height: $main-tab-height;
          }
        }

        .is-active {
          background-color: #42b983;
          border-color: #42b983;

          .el-icon {
            color: #fff;
          }

          span {
            color: #fff;
          }
        }
      }
    }
  }

  .st-tab-pane {
    .sttp-body {
      padding: 10px 10px 0 10px;

      .data-table {
        .dt-toolbar,
        .dt-search,
        .dt-main,
        .dt-pagination {
          padding: 10px;
          background-color: #fff;
        }

        .dt-search {
          margin-bottom: 10px;

          .el-form-item {
            margin: 9px 20px 9px 0;
          }

          .dts-btn-group {
            margin: 5px 0 5px 0;
          }
        }

        .dt-toolbar {
          label {
            font-size: 16px;
            line-height: 32px;
            font-weight: 600;
          }
        }

        .dt-pagination {
          .el-pagination {
            padding: 0 !important;
          }
        }
      }

    }
  }
}
</style>